package cc.verywell.pureblock.msg.nfs.map;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import cc.verywell.pureblock.func.node.KeyShell;
import cc.verywell.pureblock.util.unsafe.UnsafeRun;

/**
* 
* Copyright © 2019 TanYaqiu. All rights reserved.
* @author TanYaqiu 
* @address flat 601
* @date 2019年4月20日 上午11:38:14
*/
public class MEMmap implements FSmap {

	final private long capacity; 
	final private LinkedHashMap<KeyShell,byte[]> lockmap;
	
	public MEMmap(long capacity)  {
		this.capacity = capacity;
		this.lockmap = new LinkedHashMap<>((int)(capacity>>10),0.9f,true);
	}

	@Override
	public synchronized byte[] get(KeyShell key) {
		return lockmap.get(key);
	}
	@Override
	public synchronized boolean contain(KeyShell key) {
		return lockmap.containsKey(key);
	}

	private long used;
	@Override
	public synchronized boolean put(KeyShell k, byte[] bb) {
		if(lockmap.get(k)!=null)return false;
		long s = countSize(k, bb);
		if(s>capacity)return false;
		used += s;
		if(used>capacity) {
			Iterator<Map.Entry<KeyShell,byte[]>> it = lockmap.entrySet().iterator();
			while(it.hasNext() && used>capacity) {
				Map.Entry<KeyShell,byte[]> entry = it.next();
				used -= countSize(entry.getKey(),entry.getValue());
				it.remove();
			}
		}
		lockmap.put(k, bb);
		return true;
	}

	@Override
	public synchronized boolean remove(KeyShell k) {
		byte[] bb = lockmap.remove(k);
		if(bb==null)return false;
		used -= countSize(k,bb);
		return true;
	}
	
	protected long countSize(KeyShell key,byte[] value) {
		return 8+UnsafeRun.MemoryAddressSize*5+16*2+key.key.length+value.length;
	}
	
	public synchronized long getUsed() {
		return used;
	}
	
	
	@Override
	public synchronized String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("MEMmap files:").append(lockmap.size());
		sb.append(" used:").append(used).append("/").append(capacity);
		return sb.toString();
	}


}
